import java.util.*;
import java.io.*;



public class Proto {
	
	
	
	
	/*extrait d'un fichier LIF , un liste chainé des cellule vivante
	 * puis retourne cette valeur
	 *  
	 * 
	 * 
	 */
	public static LinkedList<Pair> lireLif(String fichier){
		String line;
		BufferedReader flux = null;
		LinkedList<Pair> cellule = new LinkedList<Pair>();
		try{
			flux= new BufferedReader(new FileReader(fichier));
			int y=0;
			while((line=flux.readLine())!=null){
				if(!line.substring(0,1).equals(new String("#")))
				{
				
					
					for(int i=0;i<line.length();i++)
					{
						if(line.substring(i, i+1).equals(new String("*"))){
						
							cellule.add(new Pair(i,y));
						}
						
						
					}
					
					
					
					
					
				}
				
				
				
				
			y++;
				
				
				
			}
			

			
			
			
			
			
			
			
			
			
			flux.close();
			
			
		}
		
	catch(IOException e){
		e.printStackTrace();
		System.out.print("Erreur Lecture");
		
		
	}
		finally{
			
			return cellule;
		
			
			
			
		}
		
		
		
		
		
		
		
		
		
	}
	
	
	
	/*ajoute dans la table le couple Pair et le nombre de fois ou elle apparait dans cette table
	 * 
	 * 
	 * 
	 * 
	 */
	public static void sousTrait(TreeMap<Pair,Integer> m,Pair p){
	
	 m.put(p, (m.get(p)==null)?1:m.get(p)+1);
		

		
		
	/* genere une table des cellule voisine d'une liste de cellule vivante
	 *  avec comme premier valeur Pair pour les coordonné
	 *  et comme seconde un Entier : le nombre de fois ou elle est dans cette table
	 *  
	 *  puis la retourne
	 * 
	 * 
	 * 
	 * 
	 * 	
	 */
		
	}
	public static TreeMap<Pair,Integer> genererVoisins(LinkedList<Pair> p){
		TreeMap<Pair,Integer> voisin = new TreeMap<Pair,Integer>();
		
		Iterator<Pair> it= p.iterator();
		
		
		while(it.hasNext()){
			Pair cellule= it.next();
			sousTrait(voisin,new Pair(cellule.x-1,cellule.y-1));
			sousTrait(voisin,new Pair(cellule.x-1,cellule.y));
			sousTrait(voisin,new Pair(cellule.x-1,cellule.y+1));
			sousTrait(voisin,new Pair(cellule.x,cellule.y+1));
			sousTrait(voisin,new Pair(cellule.x,cellule.y-1));
			sousTrait(voisin,new Pair(cellule.x+1,cellule.y-1));
			sousTrait(voisin,new Pair(cellule.x+1,cellule.y));
			sousTrait(voisin,new Pair(cellule.x+1,cellule.y+1));

			
			
			
			
			
		}
		
		
		
		
		
		return voisin;
		
		
		
		
		
		
		
		
		
	}
	/*à partir d'une liste des cellule vivante et de celle a coté (map)
	 * on vérifie selon les regle de survie (qu'on initialisera plus tard )
	 * puis
	 * on retourne les cellule vivante au prochain tour
	 * 
	 * 
	 * 
	 * 
	 * 
	 * 
	 */
	
	
	
	public static LinkedList<Pair> genereVie(Map<Pair,Integer> map,LinkedList<Pair> ancienVivant){
		
		LinkedList<Pair> nouveauVivant = new LinkedList<Pair>();
		Iterator<Pair> it = map.keySet().iterator();
		while(it.hasNext()){
			Pair p = it.next();
			if(map.get(p)==3)
				nouveauVivant.add(p);
			else{
				if(map.get(p)==2&&ancienVivant.contains(p))
					nouveauVivant.add(p);
			
			
			
			}
			
		}
		
		
		
		
		
		
		
		return nouveauVivant;
		
		
		
		
	}
	
	
	/*affiche a l'ecran le jeu
	 * en fonction d'une liste des cellule vivante
	 * 
	 * 
	 * 
	 * 
	 * 
	 */
	
	public static void afficher(LinkedList<Pair> list){
		Collections.sort(list);
		int minX=-50;
		int maxX=50;
		
		int minY=-5;
		int maxY=10;
		
		Iterator<Pair> it = list.iterator();
		Pair p = it.next();
		
			
			while(minY<maxY){
				
				while(minX<maxX){
					if(minX==p.x&&minY==p.y){
						System.out.print("*");
					if(it.hasNext())
						p=it.next();
					}
					else 
						System.out.print(".");
					
					
					
					
					minX++;
				}
				
				
				
				System.out.println();
				minY++;
				minX=-50 ;
				
			}
			
		
				
				
				
				
				
			}
				
				
				
				
			
			
			
			
			
		
	/*
	 * Un tour du jeu
	 * 
	 * 
	 * 	
	 */
		
		
public static LinkedList<Pair> cycle(LinkedList<Pair> cellule){
	cellule=genereVie(genererVoisins(cellule),cellule);
	afficher(cellule);
	return cellule;
	
	
	
	
}

/* genere un motif pour descrire un etat du jeu
 * on  calcule les differente distance entre les cellule
 * pour ignorer l'emplacement de base du motif, on garde juste les distance entre les 
 * differente cellule vivante
 * 
 * 
 * 
 * 
 * 
 * 
 */


public static LinkedList<Pair> genereMotif(LinkedList<Pair> vivant){
	
	
LinkedList<Pair> motif = new LinkedList<Pair>();	
Iterator<Pair> it = vivant.iterator();
if(it.hasNext()){
	
	Pair ancien =it.next();
	
	while(it.hasNext()){
		Pair nouveau = it.next();
		Pair difference = new Pair(nouveau.y-ancien.y,nouveau.x-ancien.x);
		motif.add(difference);
		ancien=nouveau;
		
		
		
		
		
		
	}
	
	return motif;
	
}
else return null;
	
	
	
	

/*retourne True si les deux motif sont pareil
 * 
 * 
 * 
 * 
 * 
 */
}

public static boolean compareMotif(LinkedList<Pair> motif1,LinkedList<Pair> motif2){
	
	

	if(motif1.equals(motif2))
		return true;
	else 
		return false;
	
	
	
	
}
	
	
	


	
	
	
	public static void main(String[] args){
		LinkedList<Pair> cellule;
		System.out.print(System.getProperty("user.dir"));
		cellule=lireLif("LIF/BREEDER.LIF");
		LinkedList<Pair> motif1= genereMotif(cellule);
		StatusFinder sfinder = new StatusFinder();
		
		int i=1;
		while(i<=30){
			
			
			LinkedList<Pair> motif2= genereMotif(cellule);
			System.out.println(motif2);
			cellule=cycle(cellule);
			sfinder.add(cellule);
			System.out.println(sfinder.status());
			
			
		
			
			
			
	try {
		Thread.sleep(100);
	} catch (InterruptedException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}
		i++	;
		}
		
	
			
		
		
	}
	
	
	
	
	
	
	
	
	
	
	
	

}
